#include "LogicSystemModule.h"
#include "LogicService.h"

#include "base/core/com_define.h"
#include "base/core/os/time.h"
#include "base/core/Profiler.h"
#include "base/core/gamemath.h"
#include "Common/Utility/ServerTime.h"
#include "ProtoBuffer/AllProtocol.h"
#include "Access/CharacterDataSet.h"
#include "Character/PlayerMgr.h"
#include "Common/Utility/AccountUtility.h"
#include "Global/LGlobalMgr.h"
#include "Character/RunBusinessPart.h"
#include "Duplicate/DuplicateMgr.h"
#include "ServerModule/LogicActivityModule.h"
#ifdef _MSC_VER
#pragma warning(disable:4100)
#pragma warning(disable:4244)
#pragma warning(disable:4102)
#endif

using namespace ProtoBuf;

LogicSystemModule::LogicSystemModule()
{

}

LogicSystemModule::~LogicSystemModule()
{

}


bool LogicSystemModule::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		return false;
	}
	//处理重定向，广播等
	pMessageDispatch->registerServerHandler(EMODULE_ID_SERV_SYS, this);
	pMessageDispatch->registerClientHandler(EMODULE_ID_SERV_SYS, this);

	g_GetEvent()->Subscribe(this, EVENT_ENTER_SCENE, 0, CREATURE_PLAYER, "LogicSystemModule::Init..");
	
	return true;
}

void LogicSystemModule::UnInit()
{
	g_GetEvent()->UnSubscribeAll(this);
	IMessageDispatch *pMessageDispatch = g_GetLogicService()->GetServiceMessageDispatch();
	if (nullptr != pMessageDispatch)
	{
		pMessageDispatch->unregisterServerHandler(EMODULE_ID_SERV_SYS);
		pMessageDispatch->unregisterClientHandler(EMODULE_ID_SERV_SYS);
	}
	
}

void LogicSystemModule::onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id /* = 0 */)
{
	switch (actionId)
	{
	case CLIENT_TO_LOGIC_PING:  //客户端ping消息
		{
			//暂时不处理
		}
		break;
	default:
		break;
	}
}
void LogicSystemModule::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case CLIENT_TO_LOGIC_PING:  //客户端ping消息
		{
			//暂时不处理
		}
		break;
	case CENTER_TO_LOGIC_SYNC_GLOBAL_DATA:
		{
			CenterToLogic_SyncGlobalData(package);
		}
		break;
	case CENTER_TO_LOGIC_GET_GLOBAL_DATA_RSP:
		{
			//中心服向逻辑服返回全服数据
			CenterToLogic_GlobalDataRet(package);
		}
		break;
	case GATE_TO_LOGIC_LOGIN_OUT:
		{
			//GateToLogicPlayerLoginOut(package);
		}
		break;
	case CENTER_TO_LOGIC_NOTIFY_DISCONNECT_RSP:	//中心服通知逻辑服 断开连接
		{
			CenterToLogicDisconnect(package);
		}
		break;
	case CENTER_TO_LOGIC_NOTIFY_RECONNECT_SUCCEED: //重连成功
		{
			 CenterToLogicReconnectSucceed(package);
		}
		break;
	case LOGIC_REGISTE_GATE_RSP:             //网关回复逻辑服注册
		{
		   GateToLogicRegisterResult(package);
		}
		break;
	case LOGIC_REGISTE_CENTER_RSP:          //中心服回复逻辑服注册
		{
		   CenterToLogicRegisterResult(package);
		}
		break;
	default:
		break;
	}
}

void LogicSystemModule::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_ENTER_SCENE:
		{
			if (nLen < (int32_t)sizeof(EnterSceneEvent))
			{
				LogErrFmtPrint("[logic] LogicSystemModule::OnExecute.....nLen < sizeof(EnterSceneEvent)....srcid:%lu, nlen:%u ",nSrcID,nLen);
				return;
			}
			EnterSceneEvent *pEnterEvent = (EnterSceneEvent*)pContext;

			LogicToCenterChangeSceneRes notify;
			notify.set_map_id(pEnterEvent->mapId);
			notify.set_scene_id(nSrcID);
			notify.set_cid(pEnterEvent->cId);
			notify.set_uid(pEnterEvent->uid);
			notify.set_clientid(pEnterEvent->clientId);
			Vector3PB *proto = notify.mutable_pos();
			if (nullptr != proto)
			{
				proto->set_x(pEnterEvent->x / 1000.0f);
				proto->set_y(pEnterEvent->y / 1000.0f);
				proto->set_z(pEnterEvent->z / 1000.0f);
			}
			if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_SERV_SYS, LOGIC_TO_CENTER_CHANGE_SCENE_RESULT, &notify))
			{
				LogErrFmtPrint("[logic] LogicSystemModule::OnExecute.....SendDataToCenter failed....cid:%lu ,mapid:%u, sceneid:%u, nlen:%u ", pEnterEvent->cId, pEnterEvent->mapId, nSrcID, nLen);
			}
		}
		break;
	default:
		break;
	}
}

//中心服向逻辑服同步全服数据
bool LogicSystemModule::CenterToLogic_SyncGlobalData(RECV_PACKAGE &package)
{
	CenterToLogicGlobalSync sycn;
	if (!sycn.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] LogicSystemModule::CenterToLogicGlobalData.....CenterToLogicGlobalSync parse failed...");
		return false;
	}
	g_GetLGlobalMgr()->UpdateGlobalData(sycn.global());

	return true;
}

//中心服向逻辑服返回全服数据
bool LogicSystemModule::CenterToLogic_GlobalDataRet(RECV_PACKAGE &package)
{
	LogicToCenterGetGlobalRsp rsp;
	if (!rsp.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] LogicSystemModule::CenterToLogic_GlobalDataRet.....LogicToCenterGetGlobalRsp parse failed...");
		return false;
	}
	g_GetLGlobalMgr()->UpdateGlobalData(rsp.global());
	return true;
}


//网关通知逻辑服玩家下线
bool LogicSystemModule::GateToLogicPlayerLoginOut(RECV_PACKAGE &package)
{
	bool result = false;
	uint32_t clientId = 0;
	Player * pPlayer = nullptr;
	GateNotifyDisConnect disconnect;
	bool retCode = disconnect.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMO_PROCESS_ERROR(retCode);
	clientId = disconnect.cid();
	//找到该玩家，置下线状态
	pPlayer = g_GetCreatureMgr()->GetPlayer(clientId);
	if (pPlayer)
	{
		pPlayer->SetAccountState(AccountGameState::ACCOUNT_GAME_STATE_LOGOUT);
	}
	result = true;
Exit0:
	return result;
}

//中心服通知逻辑服 断开连接
bool LogicSystemModule::CenterToLogicDisconnect(RECV_PACKAGE &package)
{
	CL_NotifyDisconnectRsp rsp;
	if (!rsp.ParseFromArray(package.dataAfterHead,package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] CL_NotifyDisconnectRsp parse failed....");
		return false;
	}
	//uint32_t clientId = rsp.clientid();
	CharIDType cid = rsp.cid();
	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(cid);
	if (pPlayer)
	{
		pPlayer->SetAccountState(AccountGameState::ACCOUNT_GAME_STATE_DISCONNECT);
		g_GetGActivityMgr()->OnDisconnect(pPlayer);
	}

	return true;
}

//中心服通知重连成功
bool LogicSystemModule::CenterToLogicReconnectSucceed(RECV_PACKAGE &package)
{
	CL_NotifyReconnectSucceedRsp rsp;
	if (!rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		LogErrFmtPrint("[logic] CL_NotifyDisconnectRsp parse failed....");
		return false;
	}
	//uint32_t clientId = rsp.clientid();
	CharIDType cid = rsp.cid();
	Player *pPlayer = g_GetCreatureMgr()->GetPlayer(cid);
	if (pPlayer)
	{

		//if (pPlayer->IsDead()) //死亡重连上直接复活
		//{
		//	pPlayer->OnNearBornRevive();
		//}

		pPlayer->SetCanBeSeenFlag(true);
		pPlayer->SetClientID(rsp.clientid());
		pPlayer->SetAccountState(ACCOUNT_GAME_STATE_GAMING);
		pPlayer->SynLoginInfo();
		pPlayer->SendAllSeeCreatureListToClient();
		//pPlayer->UpdateStateToClient();
		pPlayer->UpdateSeeLst();

		DuplicateMgr::Instance()->OnReconnect(pPlayer);

		//通知中心服，重连完成
		g_GetLogicService()->SendDataToCenter(EMODULE_ID_SERV_SYS, LOGIC_TO_CENTER_RECONNCECT_FINISH, &rsp);


		//发送重连成功事件
		ReconnectSucceedEvent reconnectEvent;
		reconnectEvent.cid = rsp.cid();
		g_GetEvent()->FireExecute(EVENT_RECONNECT_SUCCEED, rsp.cid(), CREATURE_PLAYER, (ReconnectSucceedEvent*)&reconnectEvent, sizeof(ReconnectSucceedEvent));

	}
	return true;
}

bool LogicSystemModule::GateToLogicRegisterResult(RECV_PACKAGE &package)
{
    bool retCode = false;
	LogicGateRegisterRsp registerResult;
	retCode = registerResult.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMOLOG_ASSERT(retCode);

	if (!registerResult.suc())
	{
		LogErrFmtPrint(" logic register to gate fail, logicId repeated, current logicId:%d", g_GetLogicService()->GetID());
		MMOLOG_ASSERT(false);
	}

	LogInfoFmtPrint(" logic register to gate sucess, current logicId:%d", g_GetLogicService()->GetID());
	return true;
}

bool LogicSystemModule::CenterToLogicRegisterResult(RECV_PACKAGE &package)
{
    bool retCode = false;
	LogicCenterRegisterRsp registerResult;
	retCode = registerResult.ParseFromArray(package.dataAfterHead, package.sizeAfterHead);
	MMOLOG_ASSERT(retCode);

	if (!registerResult.suc())
	{
		LogErrFmtPrint(" logic register to center fail, logicId repeated, current logicId:%d", g_GetLogicService()->GetID());
		MMOLOG_ASSERT(false);
	}

	LogInfoFmtPrint(" logic register to center success, current logicId:%d", g_GetLogicService()->GetID());
	return true;
}
